﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using QCCure.Core;

namespace QCCure
{
    public partial class ControlBugViewer : UserControl
    {
        private string LoadAttachmentsMessage = "Click on \"Load Attachments\" to display attachments.";

        public ControlBugViewer()
        {
            InitializeComponent();
            editorComments.ContentChangedEvent += new EventHandler<Editor.WebBrowserEvent>(editorComments_ContentChangedEvent);

        }

        void editorComments_ContentChangedEvent(object sender, Editor.WebBrowserEvent e)
        {
            DefectChanged = true;
        }

        [ReadOnly(true)]
        public QCBug Bug
        {
            get
            {
                return this.bug;
            }
            set
            {
                this.bug = value;
                populateBug();
            }
        }

        [ReadOnly(true)]
        public QCController QC { get; set; }

        [ReadOnly(true)]
        public QCBugFilter BugFields 
        { 
            get 
            {
                QCBugFilter filter = new QCBugFilter();
                foreach (object item in comboOtherFields.Items) {
                    filter.Add(item as QCBugField);
                }

                return filter;
            }
            set 
            {
                comboOtherFields.Items.AddRange(value.ToArray());
            }
        }

        public QCUser LoggedinUser
        {
            get {
                try {
                    return QC.LoggedinUser;
                } catch (Exception) {
                    // if we could not get the username, return null!
                    return null;
                }
            }
        }

        public bool EnableSave
        {
            get { return Properties.Settings.Default.allowSavingDefects; }
        }
        public event EventHandler SaveClick;
        public event EventHandler CancelClick;


        private QCBug bug;

        private void populateBug()
        {
            try
            {
                if (QC.IsConnected && this.bug != null)
                {
                    textID.Text = bug.ID;

                    IList<QCUser> users = QC.retrieveUsers();
                    textAssignedTo.Items.Clear();
                    textAssignedTo.Items.AddRange(users.ToArray());

                    foreach (QCUser user in users)
                    {
                        if (user.Username.Equals(bug.AssignedTo, StringComparison.OrdinalIgnoreCase))
                        {
                            textAssignedTo.SelectedItem = user;
                            break;
                        }
                    }

                    if (textAssignedTo.Text.Equals(""))
                    {
                        textAssignedTo.Text = bug.AssignedTo;
                    }

                    foreach (QCUser user in users)
                    {
                        if (user.Username.Equals(bug.DetectedBy, StringComparison.OrdinalIgnoreCase))
                        {
                            textDetectedBy.Text = user.ToString();
                            break;
                        }
                    }
                    if (textDetectedBy.Text.Equals(""))
                    {
                        textDetectedBy.Text = bug.DetectedBy;
                    }


                    IList<string> statusList = QC.retrieveStatusList();
                    textStatus.Items.Clear();
                    textStatus.Items.AddRange(statusList.ToArray());

                    foreach (string status in statusList)
                    {
                        if (status.Equals(bug.Status, StringComparison.OrdinalIgnoreCase))
                        {
                            textStatus.SelectedItem = status;
                            break;
                        }
                    }

                    if (textStatus.Text.Equals(""))
                    {
                        textStatus.Text = bug.Status;
                    }

                    checkHasAttachment.Checked = bug.HasAttachment;
                    checkHasChange.Checked = bug.HasChange;
                    checkIsModified.Checked = bug.Modified;
                    textPriority.Text = bug.Priority;
                    textProject.Text = bug.Project;
                    textSummary.Text = bug.Summary;
                    try
                    {
                        editorComments.BodyHtml = bug["BG_DEV_COMMENTS"];
                    }
                    catch (AccessViolationException)
                    {
                        // if the comments are not avaiable, need to blank it out
                        editorComments.BodyHtml = "";
                    }
                    catch (Exception)
                    {
                        // if the comments are not avaiable, need to blank it out
                        editorComments.BodyHtml = "";
                    }

                    try
                    {
                        editorDescription.BodyHtml = bug["BG_DESCRIPTION"];
                    }
                    catch (Exception)
                    {
                        // if the comments are not avaiable, need to blank it out
                        editorDescription.BodyHtml = "";
                    }

                    try
                    {
                        listAttachments.Items.Clear();

                        if (bug.HasAttachment)
                        {
                            listAttachments.Items.Add(LoadAttachmentsMessage);
                            ShowImageEnabled = true;
                        }
                        else
                        {
                            ShowImageEnabled = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        listAttachments.Items.Add("Unable to load Attachments");
                        listAttachments.Items.Add(ex.Message);
                    }

                    buttonSave.Enabled = Properties.Settings.Default.allowSavingDefects;

                    editorOtherField.BodyHtml = "";
                }
                else
                {
                    textID.Text = "";
                    textAssignedTo.Text = "";
                    textDetectedBy.Text = "";
                    checkHasAttachment.Checked = false;
                    checkHasChange.Checked = false;
                    checkHasAttachment.Checked = false;
                    checkHasAttachment.Checked = false;
                    textPriority.Text = "";
                    textProject.Text = "";
                    textStatus.Text = "";
                    textSummary.Text = "";
                    editorComments.BodyHtml = "";
                    checkHasAttachment.Checked = false;
                }

                this.Enabled = (this.bug != null);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to load the defect: " + ex.Message);
            }
            finally
            {
                DefectChanged = false;
            }
        }

        public bool ShowImageEnabled
        {
            get
            {
                return buttonShowImages.Visible;
            }
            set
            {
                panelShowImages.Visible = value;

                if (value)
                {
                    editorDescription.Dock = DockStyle.None;
                    editorDescription.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
                }
                else
                {
                    editorDescription.Dock = DockStyle.Fill;
                }
            }
        }

        private void updateBug()
        {
            try
            {
                if (this.bug != null)
                {
                    if (textAssignedTo.SelectedItem != null)
                    {
                        QCUser assignedToUser = textAssignedTo.SelectedItem as QCUser;
                        bug.AssignedTo = assignedToUser.Username;
                    }
                    else
                    {
                        MessageBox.Show("Unable to find user: " + textAssignedTo.Text + ", please make sure the user is corrected selected.", "Invalid Assign To User", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }

                    
                    bug.Status = textStatus.Text;

                    if (editorComments.BodyHtml != "")
                    {
                        if (editorComments.BodyHtml.Contains("<html>"))
                        {
                            bug["BG_DEV_COMMENTS"] = editorComments.BodyHtml;
                        }
                        else
                        {
                            bug["BG_DEV_COMMENTS"] = "<html><body>" + editorComments.BodyHtml + "</body></html>";
                        }
                    }
                    else
                    {
                        bug["BG_DEV_COMMENTS"] = "";
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                // warm here
            }
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            try
            {
                if (bug != null)
                {
                    updateBug();
                    bug.Post();

                    DefectChanged = false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to save the defect: " + ex.Message);
            }
            finally
            {
                try
                {
                    if (SaveClick != null)
                    {
                        SaveClick(sender, e);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("An error occured after the defect was saved: " + ex.Message);
                }
            }
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            try
            {
                if (bug != null)
                {
                    bug.Refresh();
                    populateBug();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to reload the defect: " + ex.Message);
            }
            finally
            {
                try
                {
                    if (SaveClick != null)
                    {
                        CancelClick(sender, e);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("An error occured after the defect was reloaded: " + ex.Message);
                }
            }
        }

        private void buttonApplyOtherField_Click(object sender, EventArgs e)
        {
            QCBugField field = comboOtherFields.SelectedItem as QCBugField;
            if (field != null && !string.IsNullOrWhiteSpace(field.QCName))
            {
                try
                {
                    bug[field.QCName] = editorOtherField.BodyHtml;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unable to apply new value to field '" + field.ToString() + "' due to: " + ex.Message);
                }
            }
        }

        private void comboOtherFields_SelectedIndexChanged(object sender, EventArgs e)
        {
            QCBugField field = comboOtherFields.SelectedItem as QCBugField;
            if (field != null && !string.IsNullOrWhiteSpace(field.QCName))
            {
                try
                {
                    editorOtherField.BodyHtml = bug[field.QCName];
                }
                catch (Exception ex)
                {
                    editorOtherField.BodyHtml = "Unable to retrieve field <b>" + field.ToString() + "</b> due to:<br/>" + ex.Message;
                }
            }
        }

        private void buttonDownloadAttachment_Click(object sender, EventArgs e)
        {
            if (listAttachments.SelectedItem is QCAttachment)
            {
                QCAttachment attachment = listAttachments.SelectedItem as QCAttachment;
                if (!File.Exists(attachment.FileName)) {
                    attachment.Download();
                }

                if (File.Exists(attachment.FileName))
                {
                    System.Diagnostics.Process.Start(attachment.FileName);
                }
                else
                {
                    MessageBox.Show("File is not pre-loaded, unable to find: " + attachment.FileName);
                }
            }
            else if (LoadAttachmentsMessage.Equals(listAttachments.SelectedItem))
            {
                buttonLoadAttachments_Click(sender, e);
            }
            else
            {
                MessageBox.Show("Selected item: " + listAttachments.SelectedItem + " is not an attachment");
            }
        }

        private void editorOtherField_DoubleClick(object sender, EventArgs e)
        {
            
        }

        public static readonly List<string> ImageExtensions = new List<string> { ".JPG", ".JPE", ".BMP", ".GIF", ".PNG" };

        private void buttonShowImages_Click(object sender, EventArgs e)
        {
            int counter = 0;

            editorDescription.BodyHtml = bug["BG_DESCRIPTION"];
 
            foreach (QCAttachment attachment in bug.Attachments)
            {
                if (ImageExtensions.Contains(Path.GetExtension(attachment.FileName).ToUpperInvariant()))
                {
                    if (!File.Exists(attachment.FileName))
                    {
                        attachment.Download();
                    }

                    

                    if (File.Exists(attachment.FileName))
                    {
                        editorDescription.BodyHtml += "<hr><b>" + attachment.Name + "</b><br>";

                        string styleHtml = "";

                        if (checkBoxScaleImage.Checked)
                        {
                            int maxWidth = cleanNumber(numericUpDownMaxPixels.Value);

                            styleHtml = "style=\"width:" + maxWidth + "px; height: auto;\"";
                        }

                        editorDescription.BodyHtml += "<IMG alt=\"" + attachment.FileName + "\" src=\"" + attachment.FileName + "\" " + styleHtml + "><br>";
                        
                        counter++;
                    }
                }
            }
            editorDescription.BodyHtml += "<br>Result: " + counter + " images Loaded.<br>";

        }

        private int cleanNumber(decimal value)
        {
            if (value < 0)
            {
                value = 0;
            }

            if (value > 1920)
            {
                value = 1920;
            }
            return (int)value;
        }

        private void buttonShowAllOther_Click(object sender, EventArgs e)
        {
            comboOtherFields.SelectedItem = null;
            editorOtherField.BodyHtml = "<h3>Loading all fields</h3>";

            foreach (object item in comboOtherFields.Items)
            {
                QCBugField field = item as QCBugField;

                if (field != null && !string.IsNullOrWhiteSpace(field.QCName))
                {
                    try
                    {
                        editorOtherField.BodyHtml = editorOtherField.BodyHtml + "<FONT color=#000080>" + field.Name + "</FONT> = " + bug[field.QCName] + "<BR>";
                    }
                    catch (Exception ex)
                    {
                        editorOtherField.BodyHtml = editorOtherField.BodyHtml + "<FONT color=#000080>" + field.Name + "</FONT> = <FONT color=#800000>Unable to retrieve</FONT> (" + ex.Message + ")<BR>"; 
                    }
                }
            }
        }

        private void buttonLoadAttachments_Click(object sender, EventArgs e)
        {
            IList<QCAttachment> attachments = bug.Attachments;
            listAttachments.Items.Clear();
            listAttachments.Items.AddRange(attachments.ToArray());
        }

        private void checkBoxScaleImage_CheckedChanged(object sender, EventArgs e)
        {
            labelMaxImagePixels.Visible = checkBoxScaleImage.Checked;
            numericUpDownMaxPixels.Visible = checkBoxScaleImage.Checked;
        }

        private bool DefectChanged
        {
            set
            {
                //buttonSave.Enabled = value;
                labelSaved.ImageIndex = value ? 0 : 1;
            }
            get
            {
                return labelSaved.ImageIndex == 0;
            }
        }
        
        private void textAssignedTo_SelectedIndexChanged(object sender, EventArgs e)
        {
            DefectChanged = true;
        }

        private void textAssignedTo_TextChanged(object sender, EventArgs e)
        {
            DefectChanged = true;
        }

        private void textAssignedTo_Leave(object sender, EventArgs e)
        {
            if (textAssignedTo.SelectedItem == null && textAssignedTo.Text != "")
            {
                foreach (QCUser user in textAssignedTo.Items)
                {
                    if (
                            textAssignedTo.Text.Equals(user.ToString(), StringComparison.CurrentCultureIgnoreCase) ||
                            (textAssignedTo.Text.Length > 10 && user.ToString().ToLower().Contains(textAssignedTo.Text.ToLower()))
                        )
                    {
                        textAssignedTo.SelectedItem = user;

                        DefectChanged = true;
                        break;
                    }
                }
            }
        }

        private void textStatus_TextChanged(object sender, EventArgs e)
        {
            DefectChanged = true;
        }

        private void textStatus_SelectedIndexChanged(object sender, EventArgs e)
        {
            DefectChanged = true;
        }
        
        private void textStatus_Leave(object sender, EventArgs e)
        {
            if (textStatus.SelectedItem == null && textStatus.Text != "")
            {
                foreach (string status in textStatus.Items)
                {
                    if (
                            textStatus.Text.Equals(status, StringComparison.CurrentCultureIgnoreCase) ||
                            (textStatus.Text.Length > 5 && status.ToLower().Contains(textAssignedTo.Text.ToLower())) 
                        )
                    {
                        textAssignedTo.SelectedItem = status;

                        DefectChanged = true;
                        break;
                    }
                }
            }
        }

        private void labelSaved_Click(object sender, EventArgs e)
        {
            // toggle defect change flag (just in case)
            DefectChanged = !DefectChanged;
        }

        private void listAttachments_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            buttonDownloadAttachment_Click(sender, e);
        }

        private void editorComments_InsertCommentEvent(object sender, Editor.WebBrowserEvent e)
        {
            QCUser user = LoggedinUser;
            string separator = "<BR><FONT color=#000080>________________________________________</FONT><BR>";
            string comment = "<FONT color=#000080><B>{0} &lt;{1}&gt;, {2}: </B></FONT><BR> ";

            if (!string.IsNullOrWhiteSpace(editorComments.BodyHtml))
            {
                comment = separator + comment;
            }

            if (user != null)
            {
                comment = string.Format(comment, user.FullName, user.Username, DateTime.Now.ToShortDateString());
            }
            else
            {
                comment = string.Format(comment, "[Unknown]", "[Unknown]", DateTime.Now.ToShortDateString());
            }

            editorComments.AppendText(comment);
        }
    }
}
